<?php
ignore_user_abort(true);
class CronAction extends Action {
   
	
	/**
	 * 设置代理IP等级
	 * 检测代理是否存活
	 * @deprecated
	 */
	function checkRank() {
		$model = D('Agent');
		$muti	=	isset($_GET['muti']);
		if (isset($_GET['id'])) {
			$item = $model->find($_GET['id']);
		}elseif (isset($_GET['re'])) {
			//检查已经在使用的是否已经失效
			$model->where('agt_rank in (1,2) and agt_province!="" and agt_err=0 and agt_lasttime <'.(time()-100));
			$model->order($muti?'rand()':'agt_lasttime ASC');
			$item	= $model->find();
		}elseif (isset($_GET['new'])){
			$item	=	$model->where('agt_lasttime=0')->order('rand()')->find();
		}
		else{
			$item	=	$model->where('agt_err<5')->order($muti?'rand()':'agt_lasttime ASC')->find();
		}
		if($item){
			$res = $this->setAgent($item, 'http://kojiki.server.ne.jp/etc/pj235.cgi'); // Run it!
			if (false !== $res) {
				if (preg_match('#<FONT color="yellow">(\d)</FONT>#', $res,$matches)) {
					
					$data = array(
						'agt_err'	=>	0,
						'agt_lasttime'	=>	time(),
					);
					if (isset($_GET['setrank'])) {
						$data['agt_rank'] = $matches[1];
					}
					$model->where(array('agt_id'=>$item['agt_id']))->save($data);
				};
			}else {
				$data = array(
					'agt_err'	=>	$item['agt_err']+1,
					'agt_lasttime'	=>	time(),
				);
				$model->where(array('agt_id'=>$item['agt_id']))->save($data);
			}
		}
	}
	
	/**
	 * 设置地区
	 */
	function checkLocation() {
		$model = D('Agent');
		$muti	=	isset($_GET['muti']);
		$item = $model->getIP4Location($muti);
		if($item){
			$res = $this->fetchUrl("http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip={$item['agt_ip']}"); 
			if (false !== $res) {
				$json = json_decode($res);
				if($json->ret){
						$reslult = $model->where(array('agt_id'=>$item['agt_id']))->save(array(
							'agt_province'	=>	$json->province,
							'agt_city'	=>$json->city,
							'agt_country'=>$json->country,
						));
						if ($reslult) {
							echo json_encode(1);
						}elseif(isset($_GET['debug'])) {
							echo $model->getDbError(),'<br />',$model->getError(),'<br />',$model->getLastSql();
							$model->where(array('agt_id'=>$item['agt_id']))->setInc('agt_err');
						}
				}
				else {
					echo 'Not Json';
				}
			}else {
				echo 'no html';
			}
		}else {
			echo json_encode(0);
		}
	}
	function checkLcationTb() {
		$this->checkLocationTb();
	}
	function checkLocationTb() {
		$model = D('Agent');
		$muti	=	isset($_GET['muti']);
		$item = $model->getIP4Location($muti);
		if($item){
			$res = $this->fetchUrl("http://ip.taobao.com/service/getIpInfo.php?ip={$item['agt_ip']}");
			if (FALSE !== $res) {
				$json = json_decode($res);
				if ($json && 0==$json->code) {
					$data = $json->data;
					$reslult = $model->where(array('agt_id'=>$item['agt_id']))->save(array(
							'agt_province'	=>	$json->region,
							'agt_city'	=>$data->city,
							'agt_country'=>$data->country,
					));
					if ($reslult) {
						echo json_encode(1);
					}
				}
			}
		}else {
			echo json_encode(0);
		}
	}
	
	/**
	 * 删除无效的代理IP
	 */
	function deleteErr() {
		$time = time()-3600*24*28;//28天删除一次
		$sqls = array(
			"agt_rank=0 and agt_err>3 AND agt_lasttime < $time",
			"agt_rank>0 and agt_err>5 AND agt_lasttime < $time",
		);
		foreach ($sqls as $sql){
			D('Agent')->where($sql)->delete();
		}
	}
	
	/**
	 * 采集56ads.com的公布的代理IP
	 * 测试OK
	 */
	function fetch56ads() {
		$html = $this->fetchUrl('http://www.56ads.com/proxyip/index.html');
// 		$html = $this->fetchUrl('http://www.qq.com/');
		if ($html) {
			$date = date('Y\.n\.j');
			$pattern = sprintf('#<a href="(/article/\d+/\d+\.html)" class="title">%s .+?</a>#',$date);
			if(preg_match_all($pattern, $html,$matches)){
				foreach ($matches[1] as $file){
					$html = $this->fetchUrl("http://www.56ads.com{$file}");
					if ($html) {
						D('Agent')->saveTextIp($html);
					}
				}
			}
		}
	}
	
	/**
	 * 采集youdaili.cn公布的代理IP
	 * OK
	 */
	function fetchYouDaili() {
		$html = $this->fetchUrl('http://www.youdaili.cn/');
		if ($html) {
			$data = date('m-d').'免费代理国内http代理ip地址';
			$pattern = sprintf('#<a target="_blank" href="(.+?)" title="%s">#',$data);
			if(preg_match($pattern, $html,$matches)){
				$html = $this->fetchUrl($matches[1]);
				if ($html) {
					D('Agent')->saveTextIp($html);

					//其它页数据
					$pattern = "#<a href='(\d+?_\d\.html)'>\d</a>#";
					if(preg_match_all($pattern, $html,$allmatches)){
						$basePath = explode('/', $matches[1]);
						array_pop($basePath);
						$basePath = implode('/', $basePath);
						foreach ($allmatches[1] as $file) {
							$html = $this->fetchUrl("{$basePath}/$file");
							D('Agent')->saveTextIp($html);
						}
					}
				}
			}
		}
		;
	}
	
	/**
	 * 采集goodips.com公布的高匿和普匿代理IP
	 * 已经失效，现在域名 ip.zdayye.com
	 * 测试通过
	 */
	function fetchGoodips() {
		foreach (array('http://www.goodips.com/?ip=&port=&dengji=%E6%99%AE%E5%8C%BF&adr=&checktime=&sleep=&cunhuo=&px=','http://www.goodips.com/?ip=&port=&dengji=%E9%AB%98%E5%8C%BF&adr=&checktime=&sleep=&cunhuo=&px=') as $url){
			$html = $this->fetchUrl($url);
			if ($html) {
				D('Agent')->saveTableIp($html);
			}
		}
	}
	
	/**
	 * 取xici IP
	 * 测试通过
	 */
	function fetchXici() {
		//可能要访浏览器才能得到数据
		$options = array(
				CURLOPT_HTTPHEADER=>	array(
				'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
				'Connection: keep-alive',
				// 						"Cache-Control: max-age=0",
				'Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3',
				//"X_FORWARDED_FOR: {$json->agt_ip}"
				),
				CURLOPT_ENCODING=> 'gzip,deflate',
				CURLOPT_USERAGENT=>'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.49 Safari/537.36',
		);
		$html = $this->fetchUrl('http://www.xici.net.co/nn',$options);
		if ($html) {
			$date	=	date('y-m-d');
			$html	=	preg_replace('#\s+#', '', $html);
			$html	=	str_replace('</tr>', "</tr>\n", $html);
			$pattern = <<<OEF
#
	<td>(\d+\.\d+\.\d+\.\d+)</td>
	<td>(\d+)</td>
	<td>.*?</td>
	<td>高匿</td>
	<td>(.*?)</td>
	<td>.*?</td>
	<td>{$date}\d\d:\d\d</td>
	</tr>
#
OEF;
			$pattern = preg_replace('#\s#', '', $pattern);
			if (preg_match_all($pattern, $html, $matches)) {
				$lines = array();
				foreach ($matches[0] as $i=> $m) {
					$lines[] = "{$matches[1][$i]}:{$matches[2][$i]}@{$matches[3][$i]}";
				}
				D('Agent')->saveTextIp(implode("\n", $lines));
			}else {
				Log::write('can not find xici page ip info');
			}
		}else {
			Log::write('can not get xici web page');
		}
	}
	
	function fetchZdaye() {
		return false;
		//TODO html的端口信息加密输出，再js解密
		foreach (array('http://ip.zdaye.com/?ip=&port=&adr=&checktime=&sleep=&cunhuo=&px=&nport=&nadr=&gb=2&dengji=%B8%DF%C4%E4&fgl=&login=&daochu=&api=&ct=1000') as $url ) {
			$html = $this->fetchUrl($url);
			if ($html) {
				$pattern = '#<td>(\d+\.\d+\.\d+\.\d+)</td>.+? v="(.+?)">#s';
				if ( preg_match_all($pattern,$html,$matches) ) {
					$lines=array();
					foreach($matches as $i=>$m){
						$arrPort = explode('@',$matches[2][$i]);
						$arrPort = array_map(array($this,'zdayeReplace'),$arrPort);
						$port = implode('',$arrPort);
						$lines[] = "{$matches[1][$i]}:{$port}";
					}
					var_dump($lines);
					exit();
					D('Agent')->saveTextIp(implode("\n", $lines));
				}else{
					Log::write('ip.zdaye.com regex failed');
				}
			}else{
				Log::write('fetch ip.zdaye.com failed');
			}
		}
	}
	private function zdayeReplace($str){
		$replace = array(
			6=>1,
			7=>4,
			8=>6,
			9=>0,
			10=>2,
			11=>7,
			12=>3,
			13=>8,
			14=>5,
			15=>9,
		);
		if ( !isset($replace[$str]) ) {
			Log::write('zdaye no key '.$str);
			exit();
		}
		return str_replace(array_keys($replace),array_values($replace),$str);
	}
	
	/**
	 * 取proxy.ipcn.org
	 */
	function fetchIpcn() {
		$html = $this->fetchUrl('http://proxy.ipcn.org/proxylist.html');
		if ($html && strpos($html, date('Ymd'))>0) {
			D('Agent')->saveTextIp($html);
		}
	}
	
	/**
	 *http://cn-proxy.com/ 
	 */
	function fetchCnProxy() {
		$html = $this->fetchUrl('http://cn-proxy.com/');
		if ($html) {
			D('Agent')->saveTrIp($html);
		}
	}
	
	function fetchProxy360() {
		$key = __FUNCTION__;
		$key .= date('Ymd');
		if (S($key)) {
			return;
		}
		$options = array(
				CURLOPT_HTTPHEADER=>	array(
						'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
						'Connection: keep-alive',
						// 						"Cache-Control: max-age=0",
						'Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3',
						//"X_FORWARDED_FOR: {$json->agt_ip}"
				),
				CURLOPT_ENCODING=> 'gzip,deflate',
				CURLOPT_USERAGENT=>'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.49 Safari/537.36',
		);
		$html = $this->fetchUrl('http://www.proxy360.cn/Region/China',$options);
		if ($html) {
			if (!D('Agent')->saveDivIp($html)) {
				Log::write('proxy360 no ip');
			}
			S($key,true);
		}else {
			Log::write('prxoy360 fetch failed');
		}
	}
	
	/**
	 * 删除重复的IP
	 * @deprecated
	 */
	function delRepeatIp() {
		$model = D('Agent');
		$repeatIps	=	$model->group('agt_ip')->having('count(*)>1')->field('agt_ip')->select();
		if ($repeatIps) {
			$flatIps	=	array();
			foreach ($repeatIps as $v){
				$flatIps[] = $v['agt_ip'];
			}
			$allRe = $model->where(array('agt_ip'=>array('in',$flatIps)))->select();
			
			//按IP分组
			$groupIp	=	array();
			foreach ($allRe as $item){
				if (empty($groupIp[$item['agt_ip']])) {
					$groupIp[$item['agt_ip']] = array();
				}
				$groupIp[$item['agt_ip']][] = $item;
			}
			
			//分组中的IP进行删除，只保留一个
			//分组中的IP进行删除，只保留一个
			$delIds = array();
			foreach ($groupIp as $group) {
				$toSort = array();
				foreach ($group as $item) {
					$toSort[$item['agt_id']] = 10*$item['agt_err']-$item['rank']-$item['agt_lasttime']/time() -0.5*(empty($item['agt_country'])?0:1);
				};
				asort($toSort,SORT_NUMERIC);
				unset($toSort[key($toSort)]);
				$delIds = array_merge($delIds,array_keys($toSort));
			}
			if(300<count($delIds)){
				$delIds = array_slice($delIds, 1,299);
			}
			$model->where(array('agt_id'=>array('in',$delIds)))->delete();
		}
	}
	
	
	
	/**
	 * @param string $url 取的url地址
	 * @param array $options 传给curl_setopt的参数
	 * @return boolean|string 取到的页面文本
	 */
	private function fetchUrl($url,$options=array()) {
		$ch = curl_init($url);
		$defaultOption = array(
				CURLOPT_HEADER => 0,
				CURLOPT_TIMEOUT => 10,
				CURLOPT_RETURNTRANSFER=>1,
		);
		$options = $defaultOption+$options;
		foreach ($options as $k=>$v){
			curl_setopt($ch,$k,$v);
		}
		$res = curl_exec($ch); // Run it!
		if (curl_errno($ch)) {
			echo curl_error($ch);
			return false;		
		}else {
			return $res;
		}
	}
	
	private function setAgent($item,$url,$useAget = true) {
			$model = D('Agent');
			$ch = curl_init($url);
			curl_setopt($ch, CURLOPT_HEADER, 0);
			
			if ($useAget) {
				$agentType	=	array(
					'HTTP'	=>	CURLPROXY_HTTP,
					'SOCKS4'=>	CURLPROXY_SOCKS4,
					'SOCKS5'=>	CURLPROXY_SOCKS5,
				);
				//以下代码设置代理服务器
				//是否启用代理
				curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, true);
				//代理认证模式
				curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
				//代理服务器地址
				curl_setopt($ch, CURLOPT_PROXY, $item['agt_ip']);
				//代理服务器端口
				curl_setopt($ch, CURLOPT_PROXYPORT, intval($item['agt_port']));
				//代理模式
				curl_setopt($ch, CURLOPT_PROXYTYPE, $agentType[$item['agt_type']]);
			}
			curl_setopt($ch, CURLOPT_TIMEOUT, 10);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			
			$res = curl_exec($ch); // Run it!
			if (curl_errno($ch)) {
				/*$model->where(array('agt_id'=>$item['agt_id']))->save(array(
						'agt_err'	=>	$item['agt_err']+1,
						// 					'agt_lasttime'=>time(),
				));*/
				dump($item);
				echo curl_error($ch);
				curl_close($ch);
				return false;
			}else {
				echo $res;
				curl_close($ch);
				return $res;
			}
	}
	
	/**
	 * 删除重复的代理
	 * @deprecated
	 */
	function delRepeat() {
		$model = D('Agent')->delRepeat();
	}
	
	function mvLog() {
		if ($_REQUEST['checkTime']) {
			$this->setCheckTime();
		}
		$model = D('Log');
		$model->startTrans();
		$todayTime = strtotime(date('Y-m-d 0:0:0'));
		$whereSql = "where log_datetime <$todayTime";
		if ($model->execute("insert into vw_logback select * from vw_log $whereSql")&&
				$model->execute("delete from vw_log $whereSql")) {
			$model->commit();
			echo 'OK';
		}else {
			$model->rollback();
			echo $model->getDbError();
		}
	}
	
	/**
	 * 根据反馈回来的数据，自动设置代理IP是否可用
	 */
	function setCheckTime() {
		$todayTime = strtotime(date('Y-m-d 0:0:0'));
		$whereSql = " log_datetime <$todayTime";
		$logModel = D('Log');
		$minTime = 2;
		if (isset($_REQUEST['minTime'])) {
			$minTime = max(2,intval($_REQUEST['minTime']));
		}
		$aliveIP = $logModel->where("$whereSql AND log_page IN(-1,1,2,3,4)")->group('agt_ip')->having("count(*) >= $minTime")->getField('log_id,agt_ip');
		empty($aliveIP) && $aliveIP = array();
		$deadIp = $logModel->where("$whereSql AND log_page = -2")->group('agt_ip')->having("count(*) >= $minTime")->getField('log_id,agt_ip');;
		empty($deadIp) && $deadIp = array();
		$deadIp = array_diff($deadIp,$aliveIP);
		
		$agentModel = D('Agent');
		if(isset($_GET['debug'])){
			echo $logModel->getLastSql();
			dump($aliveIP);
			dump($deadIp);
			exit;
		}
		if ($aliveIP) {
			$agentModel->where(array(
				'agt_ip' => array('IN',$aliveIP),
				'agt_err' => 0,
			))->setField('agt_lasttime',$todayTime);
		}
		if ($deadIp) {
			$agentModel->where(array(
				'agt_ip' => array('IN',$deadIp),
				'agt_err' => 0,
			))->save(array('agt_lasttime'=>$todayTime,'agt_err' => 1));
		}
		
	}
	
	/**
	 * 通过网站http://web.chacuo.net/netproxycheck测试代理IP是否可用
	 */
	function outCheck() {
		header("Content-Type: text/html; charset=UTF-8");
		$agentM = D('Agent');
		$one = $agentM->where('agt_rank<4 AND agt_type="HTTP" AND agt_country="中国" AND agt_province not in ("台湾","香港","澳门") AND agt_err<5')
						->order('agt_checktime + agt_err*3600*24 ASC')->find();
		if ($one) {
			$option = array(
				CURLOPT_POST	=>	1,
				CURLOPT_TIMEOUT	=>	12,
				CURLOPT_POSTFIELDS=> "data={$one['agt_ip']}&type=proxycheck&arg=p%3D{$one['agt_port']}_t%3D1_o%3D10",
			);
			$result = $this->fetchUrl('http://web.chacuo.net/netproxycheck',$option);
			$time = time();
			$saveData = array(
				'agt_id'	=>	$one['agt_id'],
				'agt_checktime'=>	$time,
			);
			if ($result) {
				$json = json_decode($result);
				$data = $json->data[0];
				if (FALSE!==strpos($data, '高级匿名代理')) {
					if (0==$one['agt_rank']) {
						$saveData['agt_rank']= 1;
					}
					$saveData['agt_err']	=	0;
					$saveData['agt_lasttime'] = $time;
				}elseif (FALSE!==strpos($data, 'HTTP_X_FORWARDED_FOR')){
					$saveData['agt_rank']= 4;
					$saveData['agt_lasttime'] = $time;
				}elseif (FALSE!==strpos($data, 'HTTP_VIA')){
					if (0==$one['agt_rank']) {
						$saveData['agt_rank']= 3;
					}
					$saveData['agt_err']	=	0;
					$saveData['agt_lasttime'] = $time;
				}elseif (FALSE!==strpos($data, 'HTTP_CACHE_CONTROL')){
					if (0==$one['agt_rank']) {
						$saveData['agt_rank']= 2;
					}
					$saveData['agt_err']	=	0;
					$saveData['agt_lasttime'] = $time;
				}elseif (FALSE!==strpos($data, '代理测试成功')){
					$saveData['agt_err']	=	0;
					$saveData['agt_lasttime'] = $time;
				}
				if (!empty($_REQUEST['debug']) && 'lukeqin'==$_REQUEST['debug']) {
					echo "<pre>$data</pre>";
					dump($one);
					dump($saveData);
				}
			}
			$agentM->save($saveData);
			
		}else {
			echo 'complete!';
		}
	}
	
	/**
	 * 合并用户提交的IP数据 
	 */
	function mergeUserResult() {
		D('Checkresult')->merge(empty($_REQUEST['minCnt'])?1:intval($_REQUEST['minCnt']));
	}
	
	/**
	 * 分配给用户执行的计划任务
	 */
	function task() {
		$ret = array(
			'Cron/checkLocationTb'=>10,
			'Cron/fetch56ads'=>1,
			'Cron/fetchYouDaili'=>1,
			'Cron/fetchCnProxy'=>1,
			'Cron/fetchXici'=>1,
// 			'Cron/fetchZdaye'=>1,
			'Cron/fetchIpcn'=>1,
			'Cron/checkLocation'=>10,
// 			'Cron/mergeUserResult'=>1,
			'Cron/mvLog'=>1,
// 			'Cron/outCheck'=>80,
// 			'Cron/fetchProxy360'=>1,
		);
		echo json_encode($ret);
	}
	
}
